{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "35434ff7",
   "metadata": {},
   "source": [
    "在 Python 中，`yield` 是一个用于定义生成器（generator）的关键字。生成器是一种特殊的迭代器，它允许你在需要时逐个生成值，而不是一次性生成所有值，从而节省内存并提高效率。以下是关于 `yield` 的详细解释：\n",
    "\n",
    "\n",
    "### **1. 基本概念**\n",
    "- **生成器函数**：使用 `yield` 的函数被称为生成器函数。当调用生成器函数时，它不会立即执行函数体，而是返回一个生成器对象。\n",
    "- **`yield` 的作用**：在函数执行过程中，`yield` 会暂停函数的执行，并返回一个值给调用者。下次调用生成器的 `__next__()` 方法时，函数会从上次暂停的位置继续执行，直到再次遇到 `yield` 或函数结束。\n",
    "\n",
    "\n",
    "### **2. 核心特点**\n",
    "#### 2.1 **惰性求值**\n",
    "生成器是惰性的，只有在请求下一个值时才会执行代码。这使得它特别适合处理大量数据或无限序列。\n",
    "\n",
    "**示例**：生成斐波那契数列的生成器\n",
    "```python\n",
    "def fibonacci():\n",
    "    a, b = 0, 1\n",
    "    while True:\n",
    "        yield a\n",
    "        a, b = b, a + b\n",
    "\n",
    "# 创建生成器对象\n",
    "fib_gen = fibonacci()\n",
    "\n",
    "# 按需生成值\n",
    "print(next(fib_gen))  # 输出: 0\n",
    "print(next(fib_gen))  # 输出: 1\n",
    "print(next(fib_gen))  # 输出: 1\n",
    "```\n",
    "\n",
    "#### 2.2 **节省内存**\n",
    "生成器不需要一次性存储所有值，而是实时生成，因此内存占用极少。例如，生成 1 到 1000 的所有数：\n",
    "```python\n",
    "# 列表（一次性生成所有值）\n",
    "nums_list = [i for i in range(1000)]  # 占用约 8KB 内存\n",
    "\n",
    "# 生成器（按需生成）\n",
    "nums_gen = (i for i in range(1000))   # 仅占用少量内存\n",
    "```\n",
    "\n",
    "\n",
    "### **3. 与 `return` 的区别**\n",
    "- **`return`**：终止函数的执行，并永久返回一个值。\n",
    "- **`yield`**：暂停函数的执行，返回一个值，并保留函数的状态，以便下次继续执行。\n",
    "\n",
    "**示例对比**：\n",
    "```python\n",
    "# 使用 return（普通函数）\n",
    "def return_example():\n",
    "    return 1\n",
    "    print(\"不会执行\")  # 永远不会被执行\n",
    "\n",
    "# 使用 yield（生成器函数）\n",
    "def yield_example():\n",
    "    yield 1\n",
    "    yield 2\n",
    "    yield 3\n",
    "\n",
    "# 调用生成器函数\n",
    "gen = yield_example()\n",
    "print(next(gen))  # 输出: 1\n",
    "print(next(gen))  # 输出: 2\n",
    "print(next(gen))  # 输出: 3\n",
    "```\n",
    "\n",
    "\n",
    "### **4. 生成器的使用方式**\n",
    "#### 4.1 **`next()` 方法**\n",
    "通过调用生成器的 `__next__()` 方法（或直接使用 `next()` 函数）获取下一个值。当没有更多值时，会抛出 `StopIteration` 异常。\n",
    "\n",
    "#### 4.2 **`for` 循环**\n",
    "生成器是可迭代对象，因此可以直接用于 `for` 循环，无需担心 `StopIteration` 异常。\n",
    "```python\n",
    "def countdown(n):\n",
    "    while n > 0:\n",
    "        yield n\n",
    "        n -= 1\n",
    "\n",
    "for num in countdown(3):\n",
    "    print(num)  # 输出: 3, 2, 1\n",
    "```\n",
    "\n",
    "\n",
    "### **5. 高级用法：`yield from`**\n",
    "`yield from` 用于简化生成器的嵌套，将一个生成器的操作委托给另一个生成器。\n",
    "\n",
    "**示例**：\n",
    "```python\n",
    "def sub_generator():\n",
    "    yield 1\n",
    "    yield 2\n",
    "\n",
    "def main_generator():\n",
    "    yield from sub_generator()  # 委托给 sub_generator\n",
    "    yield 3\n",
    "\n",
    "for value in main_generator():\n",
    "    print(value)  # 输出: 1, 2, 3\n",
    "```\n",
    "\n",
    "\n",
    "### **6. 应用场景**\n",
    "- **处理大数据**：如读取大文件、生成海量数据。\n",
    "- **实现迭代器协议**：简化自定义迭代器的实现。\n",
    "- **异步编程**：在协程（如 `asyncio`）中作为底层机制。\n",
    "- **无限序列**：如随机数生成、时间序列等。\n",
    "\n",
    "\n",
    "### **总结**\n",
    "`yield` 让函数变成生成器，使代码能够以惰性、高效的方式生成值。它是 Python 中处理大规模数据、优化内存的重要工具，也是理解异步编程的基础。通过 `yield`，你可以编写出更简洁、更高效的代码。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc250cdd",
   "metadata": {},
   "source": [
    "在 Python 中，生成器在执行过程中会记录当前的状态（例如局部变量的值、执行的位置等），要“清除”生成器对应记录的值并让它重新开始记录，一般有以下几种常见的方式，下面结合具体的代码示例进行说明：\n",
    "\n",
    "### 重新创建生成器对象\n",
    "生成器函数每次调用都会返回一个新的生成器对象，通过重新调用生成器函数可以创建一个全新的生成器，此时生成器的状态会被重置，就像重新开始记录一样。\n",
    "\n",
    "```python\n",
    "def countdown(n):\n",
    "    while n > 0:\n",
    "        yield n\n",
    "        n -= 1\n",
    "\n",
    "# 第一次创建生成器对象并迭代\n",
    "gen1 = countdown(3)\n",
    "for num in gen1:\n",
    "    print(num)\n",
    "\n",
    "# 重新创建生成器对象\n",
    "gen2 = countdown(3)\n",
    "for num in gen2:\n",
    "    print(num)\n",
    "```\n",
    "在上述代码中，`countdown` 是一个生成器函数。第一次创建 `gen1` 并迭代输出 `3`、`2`、`1` 后，通过再次调用 `countdown(3)` 创建 `gen2`，此时 `gen2` 会重新从初始状态开始生成值。\n",
    "\n",
    "### 使用生成器的 `close()` 方法（结合重新创建）\n",
    "生成器对象有一个 `close()` 方法，调用该方法会终止生成器的执行并释放相关资源。在调用 `close()` 后，通常需要重新创建生成器对象来重新开始。\n",
    "\n",
    "```python\n",
    "def infinite_sequence():\n",
    "    num = 0\n",
    "    while True:\n",
    "        try:\n",
    "            yield num\n",
    "            num += 1\n",
    "        except GeneratorExit:\n",
    "            print(\"生成器被关闭\")\n",
    "\n",
    "# 创建生成器对象\n",
    "gen = infinite_sequence()\n",
    "\n",
    "# 迭代生成器\n",
    "for _ in range(3):\n",
    "    print(next(gen))\n",
    "\n",
    "# 关闭生成器\n",
    "gen.close()\n",
    "\n",
    "# 重新创建生成器对象\n",
    "new_gen = infinite_sequence()\n",
    "for _ in range(3):\n",
    "    print(next(new_gen))\n",
    "```\n",
    "在这个例子中，`infinite_sequence` 是一个无限生成器。先创建 `gen` 并迭代部分值，调用 `gen.close()` 关闭生成器，然后重新创建 `new_gen` 来重新开始生成值。\n",
    "\n",
    "### 实现可重置的生成器类\n",
    "可以自定义一个类，实现迭代器协议（`__iter__` 和 `__next__` 方法），在类中添加重置方法来清除内部状态并重新开始。\n",
    "\n",
    "```python\n",
    "class ResettableGenerator:\n",
    "    def __init__(self, n):\n",
    "        self.n = n\n",
    "        self.current = n\n",
    "\n",
    "    def __iter__(self):\n",
    "        return self\n",
    "\n",
    "    def __next__(self):\n",
    "        if self.current > 0:\n",
    "            self.current -= 1\n",
    "            return self.current + 1\n",
    "        raise StopIteration\n",
    "\n",
    "    def reset(self):\n",
    "        self.current = self.n\n",
    "\n",
    "# 创建可重置的生成器对象\n",
    "rg = ResettableGenerator(3)\n",
    "\n",
    "# 迭代生成器\n",
    "for num in rg:\n",
    "    print(num)\n",
    "\n",
    "# 重置生成器\n",
    "rg.reset()\n",
    "\n",
    "# 再次迭代生成器\n",
    "for num in rg:\n",
    "    print(num)\n",
    "```\n",
    "在 `ResettableGenerator` 类中，`reset` 方法用于重置生成器的状态，通过调用 `reset` 方法可以清除之前记录的值并重新开始迭代。\n",
    "\n",
    "以上就是在 Python 中清除生成器对应记录的值并让它重新开始记录的常见方法，具体使用哪种方法可以根据实际需求和生成器的特点来决定。 "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2f9b792c",
   "metadata": {},
   "source": [
    "要让 `ResettableGenerator` 类能够像 `yield` 那样修饰任意函数并将其转换为可重置的生成器，可以通过以下步骤实现：\n",
    "\n",
    "\n",
    "### **1. 设计思路**\n",
    "- **装饰器模式**：使用类装饰器接收被装饰的函数，并返回一个可重置的生成器对象。\n",
    "- **闭包存储状态**：在装饰器内部维护函数的局部状态（如局部变量），模拟生成器的暂停和恢复。\n",
    "- **迭代器协议**：让装饰器返回的对象实现 `__iter__` 和 `__next__` 方法，支持迭代和重置。\n",
    "\n",
    "\n",
    "### **2. 实现代码**\n",
    "```python\n",
    "class ResettableGenerator:\n",
    "    def __init__(self, func):\n",
    "        self.func = func  # 被装饰的函数\n",
    "        self.generators = {}  # 存储每个实例的生成器状态\n",
    "\n",
    "    def __call__(self, *args, **kwargs):\n",
    "        # 为每次调用创建一个唯一的实例ID\n",
    "        instance_id = id(self) + id(args) + hash(tuple(sorted(kwargs.items())))\n",
    "        \n",
    "        # 检查是否已有该实例的状态\n",
    "        if instance_id not in self.generators:\n",
    "            # 创建新的生成器状态\n",
    "            gen_state = {\n",
    "                'frame': None,  # 存储函数帧\n",
    "                'args': args,\n",
    "                'kwargs': kwargs,\n",
    "                'started': False,\n",
    "                'finished': False\n",
    "            }\n",
    "            self.generators[instance_id] = gen_state\n",
    "        \n",
    "        return self.ResettableWrapper(self, instance_id)\n",
    "\n",
    "    class ResettableWrapper:\n",
    "        def __init__(self, decorator, instance_id):\n",
    "            self.decorator = decorator\n",
    "            self.instance_id = instance_id\n",
    "            self.state = decorator.generators[instance_id]\n",
    "\n",
    "        def __iter__(self):\n",
    "            return self\n",
    "\n",
    "        def __next__(self):\n",
    "            if self.state['finished']:\n",
    "                raise StopIteration\n",
    "\n",
    "            # 如果是第一次调用，创建函数帧\n",
    "            if not self.state['started']:\n",
    "                self.state['frame'] = self.decorator.func(*self.state['args'], **self.state['kwargs'])\n",
    "                self.state['started'] = True\n",
    "\n",
    "            try:\n",
    "                # 从函数帧获取下一个值\n",
    "                value = next(self.state['frame'])\n",
    "                return value\n",
    "            except StopIteration:\n",
    "                self.state['finished'] = True\n",
    "                raise\n",
    "\n",
    "        def reset(self):\n",
    "            # 重置生成器状态\n",
    "            self.state['frame'] = None\n",
    "            self.state['started'] = False\n",
    "            self.state['finished'] = False\n",
    "```\n",
    "\n",
    "\n",
    "### **3. 使用示例**\n",
    "```python\n",
    "@ResettableGenerator\n",
    "def countdown(n):\n",
    "    while n > 0:\n",
    "        yield n\n",
    "        n -= 1\n",
    "\n",
    "# 创建生成器实例\n",
    "gen = countdown(3)\n",
    "\n",
    "# 第一次迭代\n",
    "for num in gen:\n",
    "    print(num)  # 输出: 3, 2, 1\n",
    "\n",
    "# 重置生成器\n",
    "gen.reset()\n",
    "\n",
    "# 再次迭代\n",
    "for num in gen:\n",
    "    print(num)  # 输出: 3, 2, 1 (重新开始)\n",
    "```\n",
    "\n",
    "\n",
    "### **4. 核心原理**\n",
    "- **装饰器类**：`ResettableGenerator` 接收被装饰的函数，并在调用时返回 `ResettableWrapper` 实例。\n",
    "- **状态管理**：每个生成器实例的状态（如是否已启动、是否已完成）存储在 `generators` 字典中，通过唯一的 `instance_id` 区分。\n",
    "- **重置功能**：`reset()` 方法清除当前状态，允许重新开始生成值。\n",
    "\n",
    "\n",
    "### **5. 优势与限制**\n",
    "- **优势**：\n",
    "  - 可以像 `yield` 一样装饰任意生成器函数。\n",
    "  - 支持多次重置，无需重新创建生成器对象。\n",
    "  - 保持函数的原始逻辑不变。\n",
    "\n",
    "- **限制**：\n",
    "  - 比原生生成器更复杂，性能可能略低。\n",
    "  - 对于包含复杂状态的生成器，可能需要更精细的状态管理。\n",
    "\n",
    "\n",
    "### **6. 扩展应用**\n",
    "这种可重置的生成器在需要重复生成相同序列的场景中特别有用，例如：\n",
    "- 测试用例中的数据生成。\n",
    "- 游戏中的动画循环。\n",
    "- 数据处理管道的重置和重试。\n",
    "\n",
    "通过这种方式，你可以灵活地控制生成器的生命周期，实现更高效的资源利用。"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
